"""
Cloudflare Turnstile 验证工具类
文档: https://developers.cloudflare.com/turnstile/get-started/server-side-validation/
"""

from logging import getLogger
from typing import Dict, Optional

import httpx

from app.core.config import settings
from app.core.exceptions import APIException
from app.core.i18n import t

logger = getLogger(__name__)


class TurnstileHelper:
    """Cloudflare Turnstile 验证工具类"""

    VERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify"
    DEFAULT_TIMEOUT = 10.0

    def __init__(self):
        if not settings.TURNSTILE_SECRET_KEY:
            logger.error("Turnstile secret key is not configured")
            raise ValueError("Turnstile secret key is required")
        self.secret_key = settings.TURNSTILE_SECRET_KEY
        self.timeout = self.DEFAULT_TIMEOUT
        self.client = httpx.AsyncClient(timeout=self.timeout)

    async def verify_token(
        self, token: str, remote_ip: Optional[str] = None, idempotency_key: Optional[str] = None
    ) -> Dict:
        """验证 Turnstile token"""
        data = self._prepare_verification_data(token, remote_ip, idempotency_key)

        try:
            response = await self.client.post(self.VERIFY_URL, data=data)
            response.raise_for_status()
            result = response.json()

            if not result.get("success"):
                error_codes = result.get("error-codes", [])
                logger.error(f"Turnstile verification failed: {error_codes}")
                raise APIException(message=self._get_error_message(error_codes))

            return result

        except Exception as e:
            await self._handle_verification_error(e)

    def _prepare_verification_data(self, token: str, remote_ip: Optional[str], idempotency_key: Optional[str]) -> Dict:
        """准备验证请求数据"""
        data = {"secret": self.secret_key, "response": token}
        if remote_ip:
            data["remoteip"] = remote_ip
        if idempotency_key:
            data["idempotency_key"] = idempotency_key
        return data

    async def _handle_verification_error(self, error: Exception) -> None:
        """处理验证过程中的错误"""
        if isinstance(error, httpx.TimeoutException):
            logger.error("Turnstile verification timeout")
            raise APIException(message=t("error.turnstile.timeout"))
        elif isinstance(error, httpx.HTTPError):
            logger.error(f"Turnstile HTTP error: {str(error)}")
            raise APIException(message=t("error.turnstile.network_error"))
        else:
            logger.error(f"Turnstile verification error: {str(error)}")
            raise APIException(message=t("error.turnstile.verification_failed"))

    def _get_error_message(self, error_codes: list) -> str:
        """
        获取错误消息
        :param error_codes: 错误代码列表
        :return: 错误消息
        """
        if not error_codes:
            return t("error.turnstile.unknown_error")

        # 错误代码映射
        error_map = {
            "missing-input-secret": t("error.turnstile.missing_secret"),
            "invalid-input-secret": t("error.turnstile.invalid_secret"),
            "missing-input-response": t("error.turnstile.missing_token"),
            "invalid-input-response": t("error.turnstile.invalid_token"),
            "bad-request": t("error.turnstile.bad_request"),
            "timeout-or-duplicate": t("error.turnstile.timeout_duplicate"),
            "internal-error": t("error.turnstile.internal_error"),
        }

        # 返回第一个错误的消息
        first_error = error_codes[0]
        return error_map.get(first_error, t("error.turnstile.unknown_error"))

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self.client.aclose()


# 单例模式
turnstile_helper = TurnstileHelper()
